# 缓存机制+装饰器 题目


'''

1. 缓存机制：  
   - 当相同参数的函数调用时，若缓存未过期，直接返回缓存结果，不重复执行函数  
   - 若缓存已过期或无缓存，执行函数并将结果缓存  

2. 参数说明：  
   - `expire_time`：缓存过期时间（单位：秒），例如 `@smart_cache(expire_time=10)` 表示缓存10秒后失效  

3. 要求：  
   - 缓存需区分不同参数的调用（例如 `add(2,3)` 和 `add(3,4)` 视为不同的缓存）  
   - 测试需覆盖 **缓存命中**、**缓存过期**、**不同参数** 三种情况  

   
进阶思考：
1. 如果函数返回的结果是可变对象（如列表），直接缓存会有什么问题？如何解决？（提示：深拷贝）
2. 如何扩展这个装饰器，使其能限制最大缓存条目数？（如最多缓存100条，超出时按LRU淘汰）

'''

import time



# 定义函数
def smart_cache(expire_time):
    cache_list = {}
    def decorator(fun):
        cache_list[fun] = {}
        def wrapper(*args,**kwargs):

            s = str((args,kwargs))
            # print(s)

            #没有缓存的情况 ：没有执行过，参数不对
            if cache_list[fun] == {} or s not in cache_list[fun]:
                #执行
                rs =  fun(*args,**kwargs)
                n_t = time.time()
                
                cache_list[fun][s] = (rs,n_t)
                return rs
            #执行过 ,判断缓存过期没有
            else:
                nn_t = time.time()
                o_t = cache_list[fun][s][1]
                if nn_t - o_t >= expire_time:
                    #缓存过期
                    print('缓存过期')
                    rs =  fun(*args,**kwargs)
                    n_t = time.time()
                    
                    cache_list[fun][s] = (rs,n_t)
                    return rs
                else:
                    print('缓存没有过期，直接返回')
                    return cache_list[fun][s][0]

        return wrapper

    return decorator


#deepseek的答案
# import time
# from functools import wraps

# def smart_cache(expire_time):
#     cache = {}  # 缓存存储字典，结构示例：{ (函数名,参数): (结果, 缓存时间戳) }

#     def decorator(func):
#         @wraps(func)  # 保留原函数元信息（如 __name__）
#         def wrapper(*args, **kwargs):
#             # 生成唯一缓存键（区分函数和不同参数）
#             key = (func.__name__, args, frozenset(kwargs.items()))

#             # 检查缓存是否存在且未过期
#             if key in cache:
#                 result, timestamp = cache[key]
#                 if (time.time() - timestamp) < expire_time:
#                     print(f"缓存命中！直接返回缓存结果: {result}")
#                     return result

#             # 无缓存或已过期，执行函数并更新缓存
#             print("执行函数并缓存结果...")
#             result = func(*args, **kwargs)
#             cache[key] = (result, time.time())
#             return result
#         return wrapper
#     return decorator



@smart_cache(expire_time=2)  # 缓存2秒
def heavy_calculation(a, b):
    time.sleep(1)  # 模拟耗时计算
    return a + b

# 测试
print(heavy_calculation(2,3))  # 第一次调用，执行计算，返回5，耗时1秒
print(heavy_calculation(2,3))  # 立即再次调用，直接返回缓存结果5（未过期）
time.sleep(3)                  # 等待3秒（超过缓存时间）
print(heavy_calculation(2,3))  # 缓存已过期，重新执行计算，返回5，耗时1秒
print(heavy_calculation(3,4))  # 参数不同，视为新缓存，执行计算返回7

